package org.erp.store.infrastructure.mq.listener;

import com.alibaba.fastjson2.JSONObject;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.erp.common.constant.RabbitmqConstant;
import org.erp.store.infrastructure.constant.StoreRedisConstant;
import org.erp.store.domain.dto.BatchDeviceInventoryDto;
import org.erp.store.domain.dto.BatchDeviceInventoryResponseDto;
import org.erp.store.service.BatchDeviceInventoryService;
import org.erp.common.redis.service.RedisService;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;

/**
 * 批量状态更新MQ消息监听器
 *
 * @author dingding
 * @since 2025-11-19
 */
@Slf4j
@Component
public class BatchStatusUpdateMessageListener {

    @Resource
    private BatchDeviceInventoryService batchDeviceInventoryService;
    @Resource
    private RedisService redisService;




    /**
     * 处理批量状态更新消息
     */
    @RabbitListener(queues = RabbitmqConstant.ERP_STORE_QUEUE,
                     containerFactory = "rabbitListenerContainerFactory")
    public void handleBatchStatusUpdateMessage(String message,
                                             Channel channel,
                                             @Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws Exception {
        log.info("收到批量状态更新MQ消息，内容：{}", message);
        BatchDeviceInventoryDto messageDto=JSONObject.parseObject(message, BatchDeviceInventoryDto.class);
        log.info("收到批量状态更新MQ消息，操作人：{}，目标事件：{}，批次号：{}",
                messageDto.getOperateName(),
                messageDto.getTargetEvent().getMessage(),
                messageDto.getUuid());
        String lockKey =StoreRedisConstant.ERP_STORE_MQ_MESSAGE_UUID_KEY+messageDto.getUuid();
        try {
            validateMessage(messageDto);
            // 调用业务服务处理
            Boolean first = redisService.setIfAbsent(lockKey, "1", 10, TimeUnit.MINUTES);
            if (Boolean.FALSE.equals(first)) {
                channel.basicAck(deliveryTag, false);
                log.warn("重复批量状态更新消息，已忽略，批次号：{}，操作人：{}",
                        messageDto.getUuid(), messageDto.getOperateName());
                return;
            }
            BatchDeviceInventoryResponseDto response = batchDeviceInventoryService.batchUpdateStatusStrategic(messageDto);
     
            // 根据处理结果确认或拒绝消息
            if (response.getSuccessCount() > 0) {
                channel.basicAck(deliveryTag, false);
                log.info("批量状态更新处理成功，成功数量：{}，已确认消息", response.getSuccessCount());
            } else {
                channel.basicReject(deliveryTag, false);
                log.error("批量状态更新处理失败，失败数量：{}，拒绝消息",
                        response.getFailedCount());
            }

        } catch (Exception e) {
            log.error("批量状态更新处理异常，错误：{}", e.getMessage(), e);
            try { redisService.deleteObject(lockKey); } catch (Exception ignore) {}
            channel.basicReject(deliveryTag, false);
            throw e;
        }
    }

    /**
     * 消息参数校验
     */
    private void validateMessage(BatchDeviceInventoryDto messageDto) {
        if (messageDto.getTargetEvent() == null) {
            throw new IllegalArgumentException("目标状态事件不能为空");
        }
        if (messageDto.getOperateId() == null || messageDto.getOperateName() == null) {
            throw new IllegalArgumentException("操作人信息不能为空");
        }
    }


}
